home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsrmt / fsrmtDomain.c < prev    next >
C/C++ Source or Header  |  1991-05-10  |  54KB  |  1,565 lines

  1. /* 
  2.  * fsSpriteDomain.c --
  3.  *
  4.  *    This has the stubs for remote naming operations in a Sprite domain.
  5.  *    These routines are presented in pairs, the client stub followed
  6.  *    by the server stub.  The general style is for the server stub
  7.  *    to call the LocalDomain equivalent of the SpriteDomain client stub.
  8.  *    i.e. FsrmtOpen invokes via RPC Fsrmt_RpcOpen which calls
  9.  *    FslclOpen.  Occasionally a client or server stub will do some
  10.  *    extra processing, or use lower level primatives for efficiency.
  11.  *
  12.  * Copyright (C) 1987 Regents of the University of California
  13.  * All rights reserved.
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/fsrmt/RCS/fsrmtDomain.c,v 9.9 91/05/10 12:41:27 mgbaker Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27. #include <sprite.h>
  28. #include <fs.h>
  29. #include <fsconsist.h>
  30. #include <fsio.h>
  31. #include <fsutil.h>
  32. #include <fsNameOps.h>
  33. #include <fsrmtNameOpsInt.h>
  34. #include <fsprefix.h>
  35. #include <fsrmtInt.h>
  36. #include <fslcl.h>
  37. #include <fsutilTrace.h>
  38. #include <fsStat.h>
  39. #include <recov.h>
  40. #include <proc.h>
  41. #include <rpc.h>
  42. #include <vm.h>
  43. #include <dbg.h>
  44.  
  45. #include <string.h>
  46.  
  47. #ifdef SOSP91
  48. #include <sospRecord.h>
  49. #include <rpcPacket.h>
  50. #include <rpcServer.h>
  51. #endif
  52.  
  53. /*
  54.  * Used to contain fileID and stream data results from open calls.
  55.  */
  56. typedef    struct    FsPrefixReplyParam {
  57.     FsrmtUnionData    openData;
  58.     Fs_FileID    fileID;
  59. } FsPrefixReplyParam;
  60.  
  61. static ReturnStatus TwoNameOperation _ARGS_((int command, 
  62.     Fs_HandleHeader *prefixHandle1, char *relativeName1, 
  63.     Fs_HandleHeader *prefixHandle2, char *relativeName2, 
  64.     Fs_LookupArgs *lookupArgsPtr, Fs_RedirectInfo **newNameInfoPtrPtr, 
  65.     Boolean *name1ErrorPtr));
  66.  
  67. /*
  68.  *----------------------------------------------------------------------
  69.  *
  70.  * FsrmtImport --
  71.  *
  72.  *    Get a handle for a prefix.  This conducts an RPC_FS_PREFIX
  73.  *    to see if there is a server for the prefix.  If there is one this
  74.  *    routine installs a handle for it.  The pointer to the handle
  75.  *    is returned.
  76.  *
  77.  * Results:
  78.  *    FAILURE or RPC_TIMEOUT if we couldn't find a server for the prefix.
  79.  *    SUCCESS if we did find a server.  In this case the results are
  80.  *    a pointer to a handle for the prefix.
  81.  *
  82.  * Side effects:
  83.  *    State is left on the server machine about the open prefix.  The
  84.  *    responding file server is registered with the recovery module
  85.  *    so we find out when it goes away and when it reboots.
  86.  *    
  87.  *----------------------------------------------------------------------
  88.  */
  89. /*ARGSUSED*/
  90. ReturnStatus
  91. FsrmtImport(prefix, serverID, idPtr, domainTypePtr, hdrPtrPtr)
  92.     char    *prefix;        /* Prefix for which to find a server. */
  93.     int        serverID;        /* Suggested server ID.  This is the
  94.                      * broadcast address for nearby domains,
  95.                      * or a specific hostID, or a remote
  96.                      * network for remote broadcasting */
  97.     Fs_UserIDs    *idPtr;            /* IGNORED */
  98.     int        *domainTypePtr;        /* Return - FS_REMOTE_SPRITE_DOMAIN or
  99.                      *          FS_REMOTE_PSEUDO_DOMAIN */
  100.     Fs_HandleHeader **hdrPtrPtr;        /* Return - handle for prefix table */
  101. {
  102.     ReturnStatus     status;
  103.     Rpc_Storage     storage;
  104.     Fs_FileID        *fileIDPtr;    /* Returned from server */
  105.     ClientData        streamData;    /* Returned from server */
  106.     int            flags = FS_PREFIX;
  107.     FsPrefixReplyParam    prefixReplyParam;
  108.  
  109.     *hdrPtrPtr = (Fs_HandleHeader *)NIL;
  110.     *domainTypePtr = -1;
  111.  
  112.     storage.requestParamPtr = (Address) NIL;
  113.     storage.requestParamSize = 0;
  114.     storage.requestDataPtr = (Address)prefix;
  115.     storage.requestDataSize = strlen(prefix)+1;
  116.  
  117.     storage.replyParamPtr = (Address)&prefixReplyParam;
  118.     storage.replyParamSize = sizeof(FsPrefixReplyParam);
  119.     storage.replyDataPtr = (Address)NIL;
  120.     storage.replyDataSize = 0;
  121.     fileIDPtr = &(prefixReplyParam.fileID);
  122.  
  123.     status = Rpc_Call(serverID, RPC_FS_PREFIX, &storage);
  124.     /*
  125.      * It is necessary to allocate and copy over the stream data, since
  126.      * the ioOpen proc frees this space.
  127.      */
  128.     streamData = (ClientData)malloc(sizeof(FsrmtUnionData));
  129.     *((FsrmtUnionData *) streamData) = prefixReplyParam.openData;
  130.  
  131.     if (status == SUCCESS) {
  132.     /*
  133.      * Use the client-open routine to set up an I/O handle for the prefix.
  134.      */
  135.     status = (*fsio_StreamOpTable[fileIDPtr->type].ioOpen)(fileIDPtr, &flags,
  136.             rpc_SpriteID, (ClientData)streamData, prefix, hdrPtrPtr);
  137.     if (status == SUCCESS) {
  138.         /*
  139.          * Register the server with the recovery module so we find out
  140.          * when it goes away and when it reboots.
  141.          */
  142.         Recov_RebootRegister((*hdrPtrPtr)->fileID.serverID, Fsutil_Reopen,
  143.                  (ClientData)NIL);
  144.         *domainTypePtr = FS_REMOTE_SPRITE_DOMAIN;
  145.     }
  146.     }
  147.  
  148.     return(status);
  149. }
  150.  
  151. /*
  152.  *----------------------------------------------------------------------
  153.  *
  154.  * Fsrmt_RpcPrefix --
  155.  *
  156.  *    Server stub for RPC_FS_PREFIX.  This looks in the prefix
  157.  *    table for the given prefix.  If found, the handle is opened
  158.  *    for use by the client, and the resulting streamData is returned.
  159.  *
  160.  * Results:
  161.  *    If this procedure returns SUCCESS then a reply has been sent to
  162.  *    the client.  If the arguments are bad then an error is
  163.  *    returned and the main level sends back an error reply.
  164.  *
  165.  * Side effects:
  166.  *    The nameOpen routine is called on the prefix handle.  This ups
  167.  *    reference counts.
  168.  *
  169.  *----------------------------------------------------------------------
  170.  */
  171. /*ARGSUSED*/
  172. ReturnStatus
  173. Fsrmt_RpcPrefix(srvToken, clientID, command, storagePtr)
  174.     ClientData          srvToken;    /* Handle on server process passed to
  175.                      * Rpc_Reply */
  176.     int          clientID;    /* Sprite ID of client host */
  177.     int          command;    /* IGNORED */
  178.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  179.                      * request buffers and also indicate 
  180.                      * the exact amount of data in the 
  181.                      * request buffers.  The reply fields 
  182.                      * are initialized to NIL for the
  183.                      * pointers and 0 for the lengths.  
  184.                      * This can be passed to Rpc_Reply */
  185. {
  186.     char                *lookupName;
  187.     Fsprefix                *prefixPtr;
  188.     Fs_HandleHeader            *hdrPtr;
  189.     Fs_FileID                rootID;
  190.     int                    domainType;
  191.     int                    serverID;
  192.     ReturnStatus            status;
  193.     FsPrefixReplyParam            *prefixReplyPtr;
  194. #ifdef SOSP91
  195.     RpcServerState            *srvPtr = (RpcServerState *) srvToken;
  196.  
  197.     SOSP_ADD_PREFIX_TRACE(srvPtr->requestRpcHdr.clientID, 
  198.     srvPtr->requestRpcHdr.ID);
  199. #endif
  200.  
  201.  
  202.     status = Fsprefix_Lookup((char *) storagePtr->requestDataPtr,
  203.         FSPREFIX_EXPORTED | FSPREFIX_EXACT, clientID, &hdrPtr,
  204.         &rootID, &lookupName, &serverID, &domainType, &prefixPtr);
  205.     if (status == SUCCESS) {
  206.     register Rpc_ReplyMem        *replyMemPtr;
  207.     ClientData            streamData;
  208.     int                dataSize;
  209.  
  210.     prefixReplyPtr = mnew(FsPrefixReplyParam);
  211.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_EXPORT])(hdrPtr,
  212.             clientID, &prefixReplyPtr->fileID, &dataSize, &streamData);
  213.     if (status == SUCCESS) {
  214.         if (dataSize > 0) {
  215.         bcopy((Address)streamData, (Address)&prefixReplyPtr->openData,
  216.             dataSize);
  217.         free((Address)streamData);
  218.         }
  219.         storagePtr->replyParamPtr = (Address) (prefixReplyPtr);
  220.         storagePtr->replyParamSize = sizeof(FsPrefixReplyParam);
  221.         storagePtr->replyDataPtr = (Address)NIL;
  222.         storagePtr->replyDataSize = 0;
  223.  
  224.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  225.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  226.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  227.         Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  228.             (ClientData)replyMemPtr);
  229.         return(SUCCESS);
  230.     } else {
  231.         free((Address)prefixReplyPtr);
  232.         printf( "Fsrmt_RpcPrefix, export \"%s\" failed %x\n",
  233.             storagePtr->requestDataPtr, status);
  234.         Fsprefix_HandleClose(prefixPtr, FSPREFIX_ANY);
  235.     }
  236.     }
  237.     if (RPC_IS_BROADCAST(srvToken)) {
  238.     return(RPC_NO_REPLY);
  239.     } else {
  240.     return(RPC_FS_NO_PREFIX);
  241.     }
  242. }
  243.  
  244. /*
  245.  *----------------------------------------------------------------------
  246.  *
  247.  * FsrmtOpen --
  248.  *
  249.  *    Open a remote file.  This sets up and conducts an RPC_FS_OPEN
  250.  *    remote procedure call to open the remote file.  This is called
  251.  *    from Fsprefix_LookupOperation based on the prefix table.  FsrmtOpen
  252.  *    makes an RPC to FslclOpen on the remote machine, and returns
  253.  *    the streamData for use by the client-open routine.
  254.  *
  255.  * RPC: The input parameters are the Fs_OpenArgs defined in fsNameOps.h.
  256.  *    The input data is a relative name.  The return parameter is a file
  257.  *    type used by our caller to branch to the client-open routine.  The
  258.  *    return data area has two possible return values.  In the normal
  259.  *    case it is a lump of data used by the client-open routine to set
  260.  *    up the I/O handle. If the name lookup re-directs to a different
  261.  *    server then the returned data is the new pathname.
  262.  *
  263.  * Results:
  264.  *    SUCCESS, FS_REDIRECT, or some error code from the lookup on the server.
  265.  *    If FS_REDIRECT, then *newNameInfoPtr has prefix information.
  266.  *
  267.  * Side effects:
  268.  *    Allocates memory for the returned streamData or re-directed path.
  269.  *    An openCount is left up during the open as part of the open/re-open
  270.  *    synchronization.
  271.  *
  272.  *----------------------------------------------------------------------
  273.  */
  274.  
  275. ReturnStatus
  276. FsrmtOpen(prefixHandle, relativeName, argsPtr, resultsPtr, 
  277.          newNameInfoPtrPtr)
  278.     Fs_HandleHeader  *prefixHandle;    /* Token from the prefix table */
  279.     char       *relativeName;    /* The name of the file to open. */
  280.     Address       argsPtr;        /* Ref. to Fs_OpenArgs */
  281.     Address       resultsPtr;        /* Ref. to Fs_OpenResults */
  282.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  283.                      * its domain during the lookup. */
  284. {
  285.     ReturnStatus    status;
  286.     Fs_OpenResults    *openResultsPtr = (Fs_OpenResults *)resultsPtr;
  287.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  288.     char        replyName[FS_MAX_PATH_NAME_LENGTH];     /* This
  289.                      * may get filled with a
  290.                      * redirected pathname */
  291.     FsrmtOpenResultsParam    openResultsParam;
  292.     /*
  293.      * Synchronize with the re-open phase of recovery.
  294.      * We don't want opens to race with the recovery actions.
  295.      */
  296.     status = Fsprefix_OpenCheck(prefixHandle);
  297.     if (status != SUCCESS) {
  298.     return(status);
  299.     }
  300.  
  301.     /*
  302.      * Set up for the RPC.
  303.      */
  304.     storage.requestParamPtr = (Address) argsPtr;
  305. #ifdef SOSP91
  306.     storage.requestParamSize = sizeof(Fs_OpenArgsSOSP);
  307. #else
  308.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  309. #endif
  310.     storage.requestDataPtr = (Address) relativeName;
  311.     storage.requestDataSize = strlen(relativeName) + 1;
  312.     storage.replyParamPtr = (Address) &openResultsParam;
  313.     storage.replyParamSize = sizeof(FsrmtOpenResultsParam);
  314.     storage.replyDataPtr = (Address) replyName;
  315.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  316.  
  317.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_OPEN, &storage);
  318.     if (status == SUCCESS) {
  319.     /*
  320.      * Allocate space for the stream data returned by the server.
  321.      * We then copy the streamData from our stack buffer.
  322.      */
  323.     /* This assumes openResults.dataSize was filled in correctly. */
  324.     *openResultsPtr = openResultsParam.openResults;
  325.     if (openResultsPtr->dataSize == 0) {
  326.         openResultsPtr->streamData = (ClientData)NIL;
  327.     } else {
  328.         openResultsPtr->streamData =
  329.             (ClientData)malloc(openResultsPtr->dataSize);
  330.         bcopy((Address) &(openResultsParam.openData), (Address) openResultsPtr->streamData, openResultsPtr->dataSize);
  331.     }
  332.     } else if (status == FS_LOOKUP_REDIRECT) {
  333.     /*
  334.      * Allocate space for the re-directed pathname and
  335.      * copy over the structure that we have on our stack.  A large
  336.      * buffer is allocated because it is used as a work area in
  337.      * FsprefixLookupRedirect to create a new absolute pathname.
  338.      */
  339.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  340.     (*newNameInfoPtrPtr)->prefixLength = openResultsParam.prefixLength;
  341.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  342.     }
  343.     Fsprefix_OpenDone(prefixHandle);
  344.     return(status);
  345. }
  346.  
  347. /*
  348.  *----------------------------------------------------------------------
  349.  *
  350.  * Fsrmt_RpcOpen --
  351.  *
  352.  *      Service stub for the RPC_FS_OPEN call.  This unpackages parameters
  353.  *    and branches to the local open routine.
  354.  *
  355.  * Results:
  356.  *    If this procedure returns SUCCESS then a reply has been sent to
  357.  *    the client.  If the arguments are bad then an error is 
  358.  *    returned and the main level sends back an error reply.
  359.  *
  360.  * Side effects:
  361.  *    None here, see FslclOpen.
  362.  *    
  363.  *
  364.  *----------------------------------------------------------------------
  365.  */
  366. /*ARGSUSED*/
  367. ReturnStatus
  368. Fsrmt_RpcOpen(srvToken, clientID, command, storagePtr)
  369.     ClientData          srvToken;    /* Handle on server process passed to
  370.                      * Rpc_Reply */
  371.     int          clientID;    /* Sprite ID of client host */
  372.     int          command;    /* IGNORED */
  373.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  374.                      * request buffers and also indicate 
  375.                      * the exact amount of data in the 
  376.                      * request buffers.  The reply fields 
  377.                      * are initialized to NIL for the
  378.                       * pointers and 0 for the lengths.  
  379.                      * This can be passed to Rpc_Reply */
  380. {
  381.     ReturnStatus        status;
  382.     register Fs_OpenArgs        *openArgsPtr;        /* RPC parameters */
  383.     register Fs_OpenResults    *openResultsPtr;    /* RPC results */
  384.     Fs_HandleHeader        *prefixHandlePtr;    /* Handle for domain */
  385.     Fs_RedirectInfo        *newNameInfoPtr;    /* prefix info for
  386.                              * redirected lookups */
  387.     FsrmtOpenResultsParam        *openResultsParamPtr;    /* open results, etc. */
  388.     int                domainType;        /* Local or Pseudo */
  389.  
  390.  
  391.     if (Recov_GetClientState(clientID) & CLT_RECOV_IN_PROGRESS) {
  392.     Net_HostPrint(clientID, "Dropping regular open during recovery\n");
  393.     return(RPC_SERVICE_DISABLED);
  394.     }
  395.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  396.     /*
  397.      * Get a handle on the prefix.  We need to have it unlocked in case
  398.      * we do I/O on the directory.
  399.      */
  400.     prefixHandlePtr =
  401.     (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  402.         (&openArgsPtr->prefixID, clientID, &domainType);
  403.     if (prefixHandlePtr == (Fs_HandleHeader *)NIL) {
  404.     return(FS_STALE_HANDLE);
  405.     }
  406.     Fsutil_HandleUnlock(prefixHandlePtr);
  407.  
  408.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  409.     openResultsParamPtr = mnew(FsrmtOpenResultsParam);
  410.     openResultsPtr = &(openResultsParamPtr->openResults);
  411. #ifdef SOSP91
  412.     /*
  413.      * Store the size of the open args here so Fsio_FileNameOpen can
  414.      * determine whether or not the client is running a tracing kernel,
  415.      * and therefore whether or not the realID field in the open args is
  416.      * valid.  Gross, but doesn't require many changes to the code.
  417.      */
  418.     openResultsPtr->dataSize = storagePtr->requestParamSize;
  419. #endif
  420.  
  421.     fs_Stats.srvName.numReadOpens++;
  422.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_OPEN])(prefixHandlePtr,
  423.         (char *)storagePtr->requestDataPtr, (Address)openArgsPtr,
  424.         (Address)openResultsPtr, &newNameInfoPtr);
  425.     Fsutil_HandleRelease(prefixHandlePtr, FALSE);
  426.     if (status == SUCCESS) {
  427.     /*
  428.      * The open worked.  We return the whole Fs_OpenResults structure
  429.      * in the RPC parameter area, but it contains a pointer to
  430.      * stream data and a dataSize. That stream data is returned also
  431.      * as a separate field in the RPC parameter area, so it must be copied.
  432.      */
  433.     storagePtr->replyParamPtr = (Address)openResultsParamPtr;
  434.     storagePtr->replyParamSize = sizeof(FsrmtOpenResultsParam);
  435.     /* copy openData */
  436.     if (openResultsPtr->dataSize != 0 &&
  437.         ((Address)openResultsPtr->streamData) != (Address)NIL) {
  438.         bcopy((Address)openResultsPtr->streamData, (Address)&openResultsParamPtr->openData, openResultsPtr->dataSize);
  439.         free((Address)openResultsPtr->streamData);
  440.         storagePtr->replyDataPtr = (Address)NIL;
  441.         storagePtr->replyDataSize = 0;
  442.     }
  443.     } else if (status == FS_LOOKUP_REDIRECT) {
  444.     /*
  445.      * The file is not found on this server.
  446.      */
  447.     storagePtr->replyParamPtr = (Address)openResultsParamPtr;
  448.     storagePtr->replyParamSize = sizeof(FsrmtOpenResultsParam);
  449.     openResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  450.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  451.     storagePtr->replyDataPtr = (Address)malloc(storagePtr->replyDataSize);
  452.     (void)strcpy(storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  453.     free((Address)newNameInfoPtr);
  454.     }
  455.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  456.     Rpc_ReplyMem    *replyMemPtr;
  457.  
  458.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  459.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  460.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  461.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  462.         (ClientData)replyMemPtr);
  463.         return(SUCCESS);
  464.     } else {
  465.     free((Address)openResultsParamPtr);
  466.         return(status);
  467.     }
  468. }
  469.  
  470. /*
  471.  *----------------------------------------------------------------------
  472.  *
  473.  * FsrmtReopen --
  474.  *
  475.  *    Open a handle at its server.  This sets up and conducts an RPC_FS_REOPEN
  476.  *    remote procedure call to reopen the remote file handle.
  477.  *
  478.  * Results:
  479.  *    The return from the RPC.
  480.  *
  481.  * Side effects:
  482.  *    None.
  483.  *
  484.  *----------------------------------------------------------------------
  485.  */
  486.  
  487. ReturnStatus
  488. FsrmtReopen(hdrPtr, inSize, inData, outSizePtr, outData)
  489.     Fs_HandleHeader  *hdrPtr;        /* Handle to reopen */
  490.     int            inSize;        /* Size of input data */
  491.     Address        inData;        /* Input data to server's reopen proc */
  492.     int            *outSizePtr;    /* In/Out return data size */
  493.     Address        outData;    /* Return parameter block */
  494. {
  495.     register ReturnStatus    status;
  496.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  497.  
  498.     storage.requestParamPtr = inData;
  499.     storage.requestParamSize = inSize;
  500.     storage.requestDataPtr = (Address) NIL;
  501.     storage.requestDataSize = 0;
  502.     storage.replyParamPtr = outData;
  503.     storage.replyParamSize = *outSizePtr;
  504.     storage.replyDataPtr = (Address) NIL;
  505.     storage.replyDataSize = 0;
  506.  
  507.     status = Rpc_Call(hdrPtr->fileID.serverID, RPC_FS_REOPEN, &storage);
  508.     *outSizePtr = storage.replyParamSize;
  509.     return(status);
  510. }
  511.  
  512. /*
  513.  *----------------------------------------------------------------------
  514.  *
  515.  * Fsrmt_RpcReopen --
  516.  *
  517.  *    This is the service stub for RPC_FS_REOPEN.  This switches
  518.  *    out to a stream type reopen procedure.  To do this it must
  519.  *    assume that the first part of the parameter block contains
  520.  *    a fileID, the thing to be re-opened.
  521.  *
  522.  * Results:
  523.  *    If this procedure returns SUCCESS then a reply has been sent to
  524.  *    the client.  If the arguments are bad then an error is 
  525.  *    returned and the main level sends back an error reply.
  526.  *
  527.  * Side effects:
  528.  *    None.
  529.  *    
  530.  *
  531.  *----------------------------------------------------------------------
  532.  */
  533. /*ARGSUSED*/
  534. ReturnStatus
  535. Fsrmt_RpcReopen(srvToken, clientID, command, storagePtr)
  536.     ClientData          srvToken;    /* Handle on server process passed to
  537.                       * Rpc_Reply */
  538.     int          clientID;    /* Sprite ID of client host */
  539.     int          command;    /* IGNORED */
  540.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  541.                      * request buffers and also indicate 
  542.                      * the exact amount of data in the 
  543.                      * request buffers.  The reply fields 
  544.                      * are initialized to NIL for the
  545.                       * pointers and 0 for the lengths.  
  546.                      * This can be passed to Rpc_Reply */
  547. {
  548.     register Fs_FileID *fileIDPtr;
  549.     register ReturnStatus status;
  550.  
  551.     extern int fsutil_NumRecovering; /* XXX put in fsutil.h */
  552.  
  553.     if (storagePtr->requestParamSize <= 0) {
  554.     /*
  555.      * Check to make sure our parameter size is big enough to be
  556.      * a proper reopen request.  (As of 1/91, we've been suffering
  557.      * from a 0 paramSize bug in reopen requests.)
  558.      */
  559.     Net_HostPrint(clientID, "Zero-length parameters to reopen request!\n");
  560.     return FAILURE;
  561.     }
  562.     if ((Recov_GetClientState(clientID) & CLT_RECOV_IN_PROGRESS) == 0) {
  563.     Recov_SetClientState(clientID, CLT_RECOV_IN_PROGRESS);
  564.     fsutil_NumRecovering++;
  565.     if (fsutil_NumRecovering == 1) {
  566.         /*
  567.          * The print statements are tweaked so that the first client
  568.          * to recover triggers this message, and the last
  569.          * client to end recovery triggers another message.
  570.          * See fsRecovery.c for the complementary printf.
  571.          */
  572.         Net_HostPrint(clientID, "initiating recovery\n");
  573.     }
  574.     }
  575.  
  576.     fileIDPtr = (Fs_FileID *)storagePtr->requestParamPtr;
  577.     if (fileIDPtr->serverID != rpc_SpriteID) {
  578.     /*
  579.      * Filesystem version mis-match.
  580.      */
  581.     return(GEN_INVALID_ARG);
  582.     }
  583.     fileIDPtr->type = Fsio_MapRmtToLclType(fileIDPtr->type);
  584.     if (fileIDPtr->type < 0) {
  585.     return(GEN_INVALID_ARG);
  586.     }
  587.     status = (*fsio_StreamOpTable[fileIDPtr->type].reopen)((Fs_HandleHeader *)NIL,
  588.         clientID, (ClientData) storagePtr->requestParamPtr,
  589.         &storagePtr->replyParamSize,
  590.         (ClientData *)&storagePtr->replyParamPtr);
  591.  
  592.     Recov_AddHandleCountToClientState(fileIDPtr->type, clientID, status);
  593.  
  594.     if (status == SUCCESS) {
  595.     Rpc_ReplyMem    *replyMemPtr;
  596.  
  597.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  598.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  599.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  600.         Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  601.         (ClientData)replyMemPtr);
  602.     }
  603.     return(status);
  604. }
  605.  
  606. /*
  607.  * Union of things passed as close data.  Right now, it only seems to
  608.  * be cached attributes.
  609.  */
  610. typedef union FsCloseData {
  611.     Fscache_Attributes    attrs;
  612. } FsCloseData;
  613.  
  614.  
  615. /*
  616.  * Request params for the close RPC.  The data for the close is put in the
  617.  * closeData field so that it too can be byte-swapped. The field is for stream
  618.  * specific data that gets pushed back to the server when the client closes.
  619.  * Currently, it seems only to be Fscache_Attributes.
  620.  * 
  621.  */
  622.  
  623.  
  624. typedef struct FsRemoteCloseParams {
  625.     Fs_FileID    fileID;        /* File to close */
  626.     Fs_FileID    streamID;    /* Stream to close */
  627.     Proc_PID    procID;        /* Process doing the close */
  628.     int        flags;        /* Flags from the stream */
  629.     FsCloseData    closeData;    /* Seems to be only Fscache_Attributes... */
  630.     int        closeDataSize;    /* actual size of info in closeData field. */
  631. } FsRemoteCloseParams;
  632.  
  633. #ifdef SOSP91
  634. typedef struct FsRemoteCloseParamsSOSP {
  635.     Fs_FileID    fileID;        /* File to close */
  636.     Fs_FileID    streamID;    /* Stream to close */
  637.     Proc_PID    procID;        /* Process doing the close */
  638.     int        flags;        /* Flags from the stream */
  639.     FsCloseData    closeData;    /* Seems to be only Fscache_Attributes... */
  640.     int        closeDataSize;    /* actual size of info in closeData field. */
  641.     int        offset;
  642.     int        rwFlags;
  643. } FsRemoteCloseParamsSOSP;
  644. #endif
  645.  
  646. /*
  647.  *----------------------------------------------------------------------
  648.  *
  649.  * Fsrmt_Close --
  650.  *
  651.  *    Tell the server that we have closed one reference to its file.  This
  652.  *    is used by the remote file and remote device close routines.  This
  653.  *    routine uses RPC_FS_CLOSE to invoke the correct stream-type close
  654.  *    routine on the I/O server.
  655.  *
  656.  * Results:
  657.  *    SUCCESS.
  658.  *
  659.  * Side effects:
  660.  *    This marks the handle as needing recovery if the RPC fails due
  661.  *    to communication problems.
  662.  *
  663.  *----------------------------------------------------------------------
  664.  */
  665. /*ARGSUSED*/
  666. ReturnStatus
  667. Fsrmt_Close(streamPtr, clientID, procID, flags, dataSize, closeData)
  668.     Fs_Stream        *streamPtr;    /* Stream to close.  This is needed
  669.                      * (instead of I/O handle) so the
  670.                      * server can close its shadow stream */
  671.     int            clientID;    /* IGNORED, implicitly passed by RPC */
  672.     Proc_PID        procID;        /* Process ID of closer */
  673.     int            flags;        /* Flags from the stream being closed */
  674.     int            dataSize;    /* Size of *closeData, or Zero */
  675.     ClientData        closeData;    /* Copy of cached I/O attributes.
  676.                         * Sometimes NIL!  */
  677. {
  678.     Fsrmt_IOHandle    *rmtHandlePtr;    /* Handle to close */
  679.     Rpc_Storage     storage;
  680.     ReturnStatus     status;
  681.  
  682. #ifdef SOSP91
  683.     FsRemoteCloseParamsSOSP    params;
  684. #else
  685.     FsRemoteCloseParams    params;
  686. #endif
  687.  
  688.     rmtHandlePtr = (Fsrmt_IOHandle *)streamPtr->ioHandlePtr;
  689.     params.fileID = rmtHandlePtr->hdr.fileID;
  690.     params.streamID = streamPtr->hdr.fileID;
  691.     params.procID = procID;
  692.     params.flags = flags;
  693.     if (closeData != (ClientData) NIL) {
  694.     params.closeData = *((FsCloseData *)closeData);
  695.     params.closeDataSize = dataSize;
  696.     } else {
  697.     params.closeDataSize = 0;
  698.     }
  699.  
  700. #ifdef SOSP91
  701.     params.offset = streamPtr->offset;
  702.     params.rwFlags = (streamPtr->hdr.flags & FSUTIL_RW_FLAGS) >> 8;
  703. #endif
  704.     storage.requestParamPtr = (Address)¶ms;
  705.     storage.requestParamSize = sizeof(params);
  706.     storage.requestDataPtr = (Address)NIL;
  707.     storage.requestDataSize = 0;
  708.     storage.replyParamPtr = (Address)NIL;
  709.     storage.replyParamSize = 0;
  710.     storage.replyDataPtr = (Address)NIL;
  711.     storage.replyDataSize = 0;
  712.  
  713.     status = Rpc_Call(rmtHandlePtr->hdr.fileID.serverID, RPC_FS_CLOSE,&storage);
  714.  
  715.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  716.     status == RPC_SERVICE_DISABLED) {
  717.     /*
  718.      * Mark the handle as needing recovery if we can't tell the server
  719.      * about this close.
  720.      */
  721.     Fsutil_WantRecovery((Fs_HandleHeader *)rmtHandlePtr);
  722.     }
  723.     return(status);
  724. }
  725.  
  726. /*
  727.  *----------------------------------------------------------------------
  728.  *
  729.  * Fsrmt_RpcClose --
  730.  *
  731.  *    Server stub for RPC_FS_CLOSE.  This verifies the client and branches
  732.  *    to the stream-type close routine.
  733.  *
  734.  * Results:
  735.  *    STALE_HANDLE if the handle is out-of-date. FS_FILE_REMOVED is returned
  736.  *    if the file has been removed.  SUCCESS in the normal case, or
  737.  *    an error code from the stream-type close routine.
  738.  *
  739.  * Side effects:
  740.  *    None here, see the stream-type close routines.
  741.  *
  742.  *----------------------------------------------------------------------
  743.  */
  744. /*ARGSUSED*/
  745. ReturnStatus
  746. Fsrmt_RpcClose(srvToken, clientID, command, storagePtr)
  747.     ClientData          srvToken;    /* Handle on server process passed to
  748.                       * Rpc_Reply */
  749.     int          clientID;    /* Sprite ID of client host */
  750.     int          command;    /* IGNORED */
  751.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  752.                      * request buffers and also indicate 
  753.                      * the exact amount of data in the 
  754.                      * request buffers.  The reply fields 
  755.                      * are initialized to NIL for the
  756.                       * pointers and 0 for the lengths.  
  757.                      * This can be passed to Rpc_Reply */
  758. {
  759.     register    FsRemoteCloseParams    *paramsPtr;
  760.     register    Fs_Stream        *streamPtr;
  761.     register    Fs_HandleHeader        *hdrPtr;
  762.     ReturnStatus            status;
  763.     Fs_Stream                dummy;
  764.     register ClientData clientData;
  765.  
  766.     paramsPtr = (FsRemoteCloseParams *) storagePtr->requestParamPtr;
  767.  
  768.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  769.         (¶msPtr->fileID, clientID, (int *)NIL);
  770.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  771.     status = FS_STALE_HANDLE;
  772.     goto exit;
  773.     }
  774.     if (paramsPtr->streamID.type == -1) {
  775.     /*
  776.      * This is a close of a prefix handle which doesn't have a stream.
  777.      */
  778.     bzero((Address)&dummy, sizeof(Fs_Stream));
  779.     streamPtr = &dummy;
  780.     streamPtr->ioHandlePtr = hdrPtr;
  781.     } else {
  782.     streamPtr = Fsio_StreamClientVerify(¶msPtr->streamID, hdrPtr,
  783.             clientID);
  784.     if (streamPtr == (Fs_Stream *)NIL) {
  785.         printf("Fsrmt_RpcClose no stream <%d> to handle <%d,%d> client %d\n",
  786.             paramsPtr->streamID.minor,
  787.             paramsPtr->fileID.major, paramsPtr->fileID.minor,
  788.             clientID);
  789.         Fsutil_HandleRelease(hdrPtr, TRUE);
  790.         status = (paramsPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  791.                              : FS_STALE_HANDLE ;
  792.         goto exit;
  793.     }
  794.     }
  795.  
  796.     /*
  797.      * Call the file type close routine to release the I/O handle
  798.      * and clean up.  This call unlocks and decrements the reference
  799.      * count on the handle.
  800.      */
  801.     FSUTIL_TRACE_HANDLE(FSUTIL_TRACE_CLOSE, hdrPtr);
  802.     if (paramsPtr->closeDataSize != 0) {
  803.     clientData = (ClientData)¶msPtr->closeData;
  804.     } else {
  805.     clientData = (ClientData)NIL;
  806.     }
  807. #ifdef SOSP91
  808.     {
  809.     int offset;
  810.     int rwFlags;
  811.     if (storagePtr->requestParamSize != sizeof(FsRemoteCloseParamsSOSP)) {
  812.         /*
  813.          * Request is from an old kernel.  Set the offset to -1 because
  814.          * we don't know it.
  815.          */
  816.         offset = -1;
  817.         rwFlags = -1;
  818.     } else {
  819.         FsRemoteCloseParamsSOSP    *sospParamsPtr;
  820.         sospParamsPtr = (FsRemoteCloseParamsSOSP *) paramsPtr;
  821.         offset = sospParamsPtr->offset;
  822.         rwFlags = sospParamsPtr->rwFlags;
  823.     }
  824.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].close)
  825.         (streamPtr, clientID, paramsPtr->procID,
  826.         paramsPtr->flags, paramsPtr->closeDataSize, clientData,
  827.         &offset, &rwFlags);
  828.     }
  829. #else
  830.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].close)
  831.         (streamPtr, clientID, paramsPtr->procID,
  832.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  833. #endif
  834. #ifdef lint
  835.     status = Fsio_FileClose(streamPtr, clientID, paramsPtr->procID,
  836.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  837.     status = Fsio_PipeClose(streamPtr, clientID, paramsPtr->procID,
  838.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  839.     status = Fsio_DeviceClose(streamPtr, clientID, paramsPtr->procID,
  840.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  841.     status = FspdevPseudoStreamClose(streamPtr, clientID, paramsPtr->procID,
  842.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  843. #endif /* lint */
  844.     if (streamPtr != &dummy) {
  845.     /*
  846.      * Take the client of the stream's list and nuke the server's
  847.      * shadow stream if there are no client's left.
  848.      */
  849.     if (Fsio_StreamClientClose(&streamPtr->clientList, clientID)) {
  850.         Fsio_StreamDestroy(streamPtr);
  851.     } else {
  852.         Fsutil_HandleRelease(streamPtr, TRUE);
  853.     }
  854.     }
  855. exit:
  856.     /*
  857.      * Send back the reply.
  858.      */
  859.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  860.  
  861.     return(SUCCESS);    /* So Rpc_Server doesn't return a reply msg */
  862. }
  863.  
  864. /*
  865.  *----------------------------------------------------------------------
  866.  *
  867.  * FsrmtRemove --
  868.  *
  869.  *    This uses the RPC_FS_UNLINK call to invoke FslclRemove
  870.  *    on the file server.
  871.  *
  872.  * Results:
  873.  *    None.
  874.  *
  875.  * Side effects:
  876.  *    Does the remove.
  877.  *
  878.  *----------------------------------------------------------------------
  879.  */
  880. /*ARGSUSED*/
  881. ReturnStatus
  882. FsrmtRemove(prefixHandle, relativeName, argsPtr, resultsPtr, 
  883.            newNameInfoPtrPtr)
  884.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  885.     char        *relativeName;    /* The name of the file to remove */
  886.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  887.     Address        resultsPtr;        /* == NIL */
  888.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  889.                        its domain during the lookup. */
  890. {
  891.     ReturnStatus    status;
  892.     Rpc_Storage        storage;
  893.     Fs_RedirectInfo    redirectInfo;
  894.     int            prefixLength;
  895.  
  896.     storage.requestParamPtr = (Address) argsPtr;
  897.     storage.requestParamSize = sizeof(Fs_LookupArgs);
  898.     storage.requestDataPtr = (Address) relativeName;
  899.     storage.requestDataSize = strlen(relativeName) + 1;
  900.     storage.replyParamPtr = (Address) &prefixLength;
  901.     storage.replyParamSize = sizeof (int);
  902.     storage.replyDataPtr = (Address)&redirectInfo;
  903.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  904.  
  905.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_UNLINK, &storage);
  906.     if (status == FS_LOOKUP_REDIRECT) {
  907.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  908.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  909.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  910.     }
  911.     return(status);
  912. }
  913.  
  914. /*
  915.  *----------------------------------------------------------------------
  916.  *
  917.  * FsrmtRemoveDir --
  918.  *
  919.  *    Remove a directory.  This uses the RPC_FS_RMDIR call to invoke
  920.  *    FslclRemoveDir on the file server.
  921.  *
  922.  * Results:
  923.  *    None.
  924.  *
  925.  * Side effects:
  926.  *    Does the remove.
  927.  *
  928.  *----------------------------------------------------------------------
  929.  */
  930. /*ARGSUSED*/
  931. ReturnStatus
  932. FsrmtRemoveDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  933.            newNameInfoPtrPtr)
  934.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  935.     char        *relativeName;    /* The name of the file to remove */
  936.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  937.     Address        resultsPtr;        /* == NIL */
  938.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  939.                        its domain during the lookup. */
  940. {
  941.     ReturnStatus    status;
  942.     Rpc_Storage        storage;
  943.     Fs_RedirectInfo    redirectInfo;
  944.     int            prefixLength;
  945.  
  946.     storage.requestParamPtr = (Address) argsPtr;
  947.     storage.requestParamSize = sizeof(Fs_LookupArgs);
  948.     storage.requestDataPtr = (Address) relativeName;
  949.     storage.requestDataSize = strlen(relativeName) + 1;
  950.     storage.replyParamPtr = (Address) &prefixLength;
  951.     storage.replyParamSize = sizeof (int);
  952.     storage.replyDataPtr = (Address)&redirectInfo;
  953.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  954.  
  955.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_RMDIR, &storage);
  956.     if (status == FS_LOOKUP_REDIRECT) {
  957.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  958.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  959.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  960.     }
  961.     return(status);
  962. }
  963.  
  964. /*
  965.  *----------------------------------------------------------------------
  966.  *
  967.  * Fsrmt_RpcRemove --
  968.  *
  969.  *    The service stub for FS_RPC_UNLINK use to remove a file or directory.
  970.  *
  971.  * Results:
  972.  *    If this procedure returns SUCCESS then a reply has been sent to
  973.  *    the client.  If the arguments are bad then an error is 
  974.  *    returned and the main level sends back an error reply.
  975.  *
  976.  * Side effects:
  977.  *    None.
  978.  *
  979.  *----------------------------------------------------------------------
  980.  */
  981. /*ARGSUSED*/
  982. ReturnStatus
  983. Fsrmt_RpcRemove(srvToken, clientID, command, storagePtr)
  984.     ClientData          srvToken;    /* Handle on server process passed to
  985.                       * Rpc_Reply */
  986.     int          clientID;    /* Sprite ID of client host */
  987.     int          command;    /* RPC_FS_UNLINK, RPC_FS_RMDIR */
  988.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  989.                      * request buffers and also indicate 
  990.                      * the exact amount of data in the 
  991.                      * request buffers.  The reply fields 
  992.                      * are initialized to NIL for the
  993.                       * pointers and 0 for the lengths.  
  994.                      * This can be passed to Rpc_Reply */
  995. {
  996.     ReturnStatus    status;
  997.     Fs_HandleHeader    *prefixHandlePtr;
  998.     Fs_RedirectInfo    *newNameInfoPtr;
  999.     Fs_LookupArgs    *lookupArgsPtr;
  1000.     int            domainType;
  1001.  
  1002.     lookupArgsPtr = (Fs_LookupArgs *)storagePtr->requestParamPtr;
  1003.     prefixHandlePtr =
  1004.     (*fsio_StreamOpTable[lookupArgsPtr->prefixID.type].clientVerify)
  1005.         (&lookupArgsPtr->prefixID, clientID, &domainType);
  1006.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1007.     return(FS_STALE_HANDLE);
  1008.     } 
  1009.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1010.  
  1011.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1012.     switch (command) {
  1013.     case RPC_FS_UNLINK:
  1014.         fs_Stats.srvName.removes++;
  1015.         command = FS_DOMAIN_REMOVE;
  1016.         break;
  1017.     case RPC_FS_RMDIR:
  1018.         fs_Stats.srvName.removeDirs++;
  1019.         command = FS_DOMAIN_REMOVE_DIR;
  1020.         break;
  1021.     default:
  1022.         return(GEN_INVALID_ARG);
  1023.     }
  1024.     status = (*fs_DomainLookup[domainType][command])(prefixHandlePtr,
  1025.             (char *) storagePtr->requestDataPtr,
  1026.             (Address) lookupArgsPtr, (Address) NIL, &newNameInfoPtr);
  1027.     if (status == FS_LOOKUP_REDIRECT) {
  1028.     Rpc_ReplyMem    *replyMemPtr;
  1029.  
  1030.     storagePtr->replyDataPtr = (Address) newNameInfoPtr;
  1031.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1032.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1033.     storagePtr->replyParamSize = sizeof (int);
  1034.     *((int *) (storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1035.  
  1036.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1037.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1038.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1039.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1040.         (ClientData)replyMemPtr);
  1041.     } else {
  1042.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1043.         (ClientData)NIL);
  1044.     }
  1045.  
  1046.     return(SUCCESS);
  1047. }
  1048.  
  1049.  
  1050. /*
  1051.  *----------------------------------------------------------------------
  1052.  *
  1053.  * FsrmtMakeDir --
  1054.  *
  1055.  *    Make the named directory.  This uses the RPC_FS_MAKE_DIR call
  1056.  *    to invoke FslclMakeDir on the file server.
  1057.  *
  1058.  * Results:
  1059.  *    A return code from the file server or the RPC.
  1060.  *
  1061.  * Side effects:
  1062.  *    Makes the directory.
  1063.  *
  1064.  *----------------------------------------------------------------------
  1065.  */
  1066. /*ARGSUSED*/
  1067. ReturnStatus
  1068. FsrmtMakeDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1069.         newNameInfoPtrPtr)
  1070.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  1071.     char        *relativeName;   /* The name of the directory to create */
  1072.     Address        argsPtr;        /* Ref. to Fs_OpenArgs */
  1073.     Address        resultsPtr;        /* == NIL */
  1074.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  1075.                     * its domain during the lookup. */
  1076. {
  1077.     ReturnStatus    status;
  1078.     Rpc_Storage        storage;
  1079.     Fs_RedirectInfo    redirectInfo;
  1080.     int            prefixLength;
  1081.  
  1082.     storage.requestParamPtr = (Address) argsPtr;
  1083.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  1084.     storage.requestDataPtr = (Address) relativeName;
  1085.     storage.requestDataSize = strlen(relativeName) + 1;
  1086.     storage.replyParamPtr = (Address) &prefixLength;
  1087.     storage.replyParamSize = sizeof (int);
  1088.     storage.replyDataPtr = (Address)&redirectInfo;
  1089.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1090.  
  1091.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_MKDIR, &storage);
  1092.     if (status == FS_LOOKUP_REDIRECT) {
  1093.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1094.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1095.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1096.     }
  1097.     return(status);
  1098. }
  1099.  
  1100. /*
  1101.  *----------------------------------------------------------------------
  1102.  *
  1103.  * Fsrmt_RpcMakeDir --
  1104.  *
  1105.  *    Handle a make directory request from a client.
  1106.  *
  1107.  * Results:
  1108.  *    If this procedure returns SUCCESS then a reply has been sent to
  1109.  *    the client.  If the arguments are bad then an error is 
  1110.  *    returned and the main level sends back an error reply.
  1111.  *
  1112.  * Side effects:
  1113.  *    None.
  1114.  *
  1115.  *----------------------------------------------------------------------
  1116.  */
  1117.  
  1118. /*ARGSUSED*/
  1119. ReturnStatus
  1120. Fsrmt_RpcMakeDir(srvToken, clientID, command, storagePtr)
  1121.     ClientData          srvToken;    /* Handle on server process passed to
  1122.                       * Rpc_Reply */
  1123.     int          clientID;    /* Sprite ID of client host */
  1124.     int          command;    /* Command identifier */
  1125.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1126.                      * request buffers and also indicate 
  1127.                      * the exact amount of data in the 
  1128.                      * request buffers.  The reply fields 
  1129.                      * are initialized to NIL for the
  1130.                       * pointers and 0 for the lengths.  
  1131.                      * This can be passed to Rpc_Reply */
  1132. {
  1133.     ReturnStatus    status;
  1134.     Fs_HandleHeader    *prefixHandlePtr;
  1135.     Fs_RedirectInfo    *newNameInfoPtr;
  1136.     Fs_OpenArgs        *openArgsPtr;
  1137.     int            domainType;
  1138.  
  1139.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  1140.     if (openArgsPtr->prefixID.serverID != rpc_SpriteID) {
  1141.     return(GEN_INVALID_ARG);
  1142.     }
  1143.  
  1144.     prefixHandlePtr =
  1145.     (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  1146.         (&openArgsPtr->prefixID, clientID, &domainType);
  1147.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1148.     return(FS_STALE_HANDLE);
  1149.     }
  1150.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1151.  
  1152.     fs_Stats.srvName.makeDirs++;
  1153.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1154.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_MAKE_DIR])(prefixHandlePtr,
  1155.         (char *)storagePtr->requestDataPtr,
  1156.         (Address) openArgsPtr, (Address) NIL, &newNameInfoPtr);
  1157.     if (status == FS_LOOKUP_REDIRECT) {
  1158.     Rpc_ReplyMem    *replyMemPtr;
  1159.  
  1160.     storagePtr->replyDataPtr = (Address)newNameInfoPtr;
  1161.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1162.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1163.     storagePtr->replyParamSize = sizeof (int);
  1164.     *((int *)(storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1165.  
  1166.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1167.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1168.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1169.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1170.         (ClientData)replyMemPtr);
  1171.     } else {
  1172.         Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1173.         (ClientData)NIL);
  1174.     }
  1175.  
  1176.     return(SUCCESS);
  1177. }
  1178.  
  1179.  
  1180. /*
  1181.  *----------------------------------------------------------------------
  1182.  *
  1183.  * FsrmtMakeDevice --
  1184.  *
  1185.  *    Create a device file.  This uses the RPC_FS_MAKE_DEV call to create
  1186.  *    the special file on the file server.
  1187.  *
  1188.  * Results:
  1189.  *    None.
  1190.  *
  1191.  * Side effects:
  1192.  *    Makes a device file.
  1193.  *
  1194.  *----------------------------------------------------------------------
  1195.  */
  1196. /*ARGSUSED*/
  1197. ReturnStatus
  1198. FsrmtMakeDevice(prefixHandle, relativeName, argsPtr, resultsPtr,
  1199.                    newNameInfoPtrPtr)
  1200.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  1201.     char           *relativeName;   /* The name of the file. */
  1202.     Address        argsPtr;        /* Ref. to FsMakeDevArgs */
  1203.     Address        resultsPtr;        /* == NIL */
  1204.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  1205.                     * its domain during the lookup. */
  1206. {
  1207.     ReturnStatus    status;
  1208.     Rpc_Storage        storage;
  1209.     Fs_RedirectInfo    redirectInfo;
  1210.     int            prefixLength;
  1211.  
  1212.     storage.requestParamPtr = (Address) argsPtr;
  1213.     storage.requestParamSize = sizeof(Fs_MakeDeviceArgs);
  1214.     storage.requestDataPtr = (Address) relativeName;
  1215.     storage.requestDataSize = strlen(relativeName) + 1;
  1216.     storage.replyParamPtr = (Address) &prefixLength;
  1217.     storage.replyParamSize = sizeof (int);
  1218.     storage.replyDataPtr = (Address)&redirectInfo;
  1219.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1220.  
  1221.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_MKDEV, &storage);
  1222.     if (status == FS_LOOKUP_REDIRECT) {
  1223.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1224.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1225.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1226.     }
  1227.     return(status);
  1228. }
  1229.  
  1230. /*
  1231.  *----------------------------------------------------------------------
  1232.  *
  1233.  * Fsrmt_RpcMakeDev --
  1234.  *
  1235.  *    Service stub for RPC_FS_MKDEV.  This calls FslclMakeDevice.
  1236.  *
  1237.  * Results:
  1238.  *    If this procedure returns SUCCESS then a reply has been sent to
  1239.  *    the client.  If the arguments are bad then an error is 
  1240.  *    returned and the main level sends back an error reply.
  1241.  *
  1242.  * Side effects:
  1243.  *    None.
  1244.  *
  1245.  *----------------------------------------------------------------------
  1246.  */
  1247.  
  1248. /*ARGSUSED*/
  1249. ReturnStatus
  1250. Fsrmt_RpcMakeDev(srvToken, clientID, command, storagePtr)
  1251.     ClientData          srvToken;    /* Handle on server process passed to
  1252.                       * Rpc_Reply */
  1253.     int          clientID;    /* Sprite ID of client host */
  1254.     int          command;    /* Command identifier */
  1255.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1256.                      * request buffers and also indicate 
  1257.                      * the exact amount of data in the 
  1258.                      * request buffers.  The reply fields 
  1259.                      * are initialized to NIL for the
  1260.                       * pointers and 0 for the lengths.  
  1261.                      * This can be passed to Rpc_Reply */
  1262. {
  1263.     ReturnStatus    status;
  1264.     Fs_MakeDeviceArgs    *makeDevArgsPtr;
  1265.     Fs_HandleHeader    *prefixHandlePtr;
  1266.     Fs_RedirectInfo    *newNameInfoPtr;
  1267.     int            domainType;
  1268.  
  1269.     makeDevArgsPtr = (Fs_MakeDeviceArgs *) storagePtr->requestParamPtr;
  1270.     prefixHandlePtr = 
  1271.     (*fsio_StreamOpTable[makeDevArgsPtr->open.prefixID.type].clientVerify)
  1272.         (&makeDevArgsPtr->open.prefixID, clientID, &domainType);
  1273.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1274.     return(FS_STALE_HANDLE);
  1275.     }
  1276.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1277.  
  1278.     fs_Stats.srvName.makeDevices++;
  1279.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1280.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_MAKE_DEVICE])(prefixHandlePtr,
  1281.         (char *)storagePtr->requestDataPtr, (Address) makeDevArgsPtr,
  1282.         (Address) NIL, &newNameInfoPtr);
  1283.     if (status == FS_LOOKUP_REDIRECT) {
  1284.     Rpc_ReplyMem    *replyMemPtr;
  1285.  
  1286.     storagePtr->replyDataPtr = (Address)newNameInfoPtr;
  1287.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1288.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1289.     storagePtr->replyParamSize = sizeof (int);
  1290.     *((int *) (storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1291.  
  1292.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1293.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1294.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1295.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1296.             (ClientData)replyMemPtr);
  1297.     } else {
  1298.         Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1299.             (ClientData)NIL);
  1300.     }
  1301.     return(SUCCESS);
  1302. }
  1303.  
  1304. /*
  1305.  *----------------------------------------------------------------------
  1306.  *
  1307.  * TwoNameOperation --
  1308.  *
  1309.  *    Common stub for renaming a file or making a hard link.
  1310.  *
  1311.  * Results:
  1312.  *    A return status.
  1313.  *
  1314.  * Side effects:
  1315.  *    None.
  1316.  *
  1317.  *----------------------------------------------------------------------
  1318.  */
  1319. static ReturnStatus
  1320. TwoNameOperation(command, prefixHandle1, relativeName1, prefixHandle2, 
  1321.      relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1322.     int            command;        /* Which Rpc: Mv or Ln */
  1323.     Fs_HandleHeader     *prefixHandle1;        /* Handle from prefix table */
  1324.     char         *relativeName1;        /* The new name of the file. */
  1325.     Fs_HandleHeader     *prefixHandle2;        /* Handle from prefix table */
  1326.     char         *relativeName2;        /* The new name of the file. */
  1327.     Fs_LookupArgs    *lookupArgsPtr;        /* Contains IDs */
  1328.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  1329.                          * leaves its domain during the
  1330.                          * lookup. */
  1331.     Boolean         *name1ErrorPtr;        /* If we return REDIRECT or
  1332.                          * STALE_HANDLE this indicates
  1333.                          * if that applies to the first
  1334.                          * pathname or the second */
  1335. {
  1336.     Fs_2PathParams    params;
  1337.     Fs_2PathData        *requestDataPtr;    /* too big for stack */
  1338.     Fs_2PathReply    replyParams;
  1339.     Rpc_Storage        storage;
  1340.     ReturnStatus    status;
  1341.     Fs_RedirectInfo    redirectInfo;
  1342.  
  1343.     requestDataPtr = mnew(Fs_2PathData);
  1344.  
  1345.     params.lookup = *lookupArgsPtr;
  1346.     params.lookup.prefixID = prefixHandle1->fileID;
  1347.     params.prefixID2 = prefixHandle2->fileID;
  1348.  
  1349.     (void)strcpy(requestDataPtr->path1, relativeName1);
  1350.     (void)strcpy(requestDataPtr->path2, relativeName2);
  1351.  
  1352.     storage.requestParamPtr = (Address) ¶ms;
  1353.     storage.requestParamSize = sizeof (Fs_2PathParams);
  1354.     storage.requestDataPtr = (Address) requestDataPtr;
  1355.     storage.requestDataSize = sizeof (Fs_2PathData);
  1356.  
  1357.     storage.replyParamPtr = (Address) &replyParams;
  1358.     storage.replyParamSize = sizeof (Fs_2PathReply);
  1359.     storage.replyDataPtr = (Address)&redirectInfo;
  1360.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1361.  
  1362.     status = Rpc_Call(prefixHandle1->fileID.serverID, command, &storage);
  1363.     *name1ErrorPtr = replyParams.name1ErrorP;
  1364.     if (status == FS_LOOKUP_REDIRECT) {
  1365.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1366.     (*newNameInfoPtrPtr)->prefixLength = replyParams.prefixLength;
  1367.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1368.     }
  1369.     free((Address)requestDataPtr);
  1370.  
  1371.     return(status);
  1372. }
  1373.  
  1374. /*
  1375.  *----------------------------------------------------------------------
  1376.  *
  1377.  * Fsrmt_Rpc2Path --
  1378.  *
  1379.  *    Common service stub for FsrmtRename and FsrmtHardLink.
  1380.  *
  1381.  * Results:
  1382.  *    If this procedure returns SUCCESS then a reply has been sent to
  1383.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  1384.  *    returned and the main level sends back an error reply.
  1385.  *
  1386.  * Side effects:
  1387.  *    Calls the local rename or hard link routine to attempt the lock 
  1388.  *    operation.
  1389.  *
  1390.  *----------------------------------------------------------------------
  1391.  */
  1392. ReturnStatus
  1393. Fsrmt_Rpc2Path(srvToken, clientID, command, storagePtr)
  1394.     ClientData srvToken;    /* Handle on server process passed to
  1395.                  * Rpc_Reply */
  1396.     int clientID;        /* Sprite ID of client host */
  1397.     int command;        /* Command identifier */
  1398.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1399.                  * buffers and also indicate the exact amount
  1400.                  * of data in the request buffers.  The reply
  1401.                  * fields are initialized to NIL for the
  1402.                  * pointers and 0 for the lengths.  This can
  1403.                  * be passed to Rpc_Reply */
  1404. {
  1405.     register    Fs_2PathParams        *paramsPtr;
  1406.     register    Fs_LookupArgs        *lookupArgsPtr;
  1407.     register    Fs_HandleHeader        *prefixHandle1Ptr;
  1408.     register    Fs_HandleHeader        *prefixHandle2Ptr;
  1409.     register    Rpc_ReplyMem        *replyMemPtr;
  1410.     Fs_RedirectInfo            *newNameInfoPtr;
  1411.     Boolean                name1Error = FALSE;
  1412.     Fs_2PathReply            *replyParamsPtr;
  1413.     Fs_2PathData                *pathDataPtr;
  1414.     ReturnStatus            status = SUCCESS;
  1415.     int                    domainType;
  1416.  
  1417.     paramsPtr = (Fs_2PathParams *)storagePtr->requestParamPtr;
  1418.     pathDataPtr = (Fs_2PathData *)storagePtr->requestDataPtr;
  1419.     lookupArgsPtr = ¶msPtr->lookup;
  1420.     prefixHandle1Ptr =
  1421.     (*fsio_StreamOpTable[lookupArgsPtr->prefixID.type].clientVerify)
  1422.         (&lookupArgsPtr->prefixID, clientID, &domainType);
  1423.  
  1424.     if (prefixHandle1Ptr == (Fs_HandleHeader *)NIL) {
  1425.     name1Error = TRUE;
  1426.     status = FS_STALE_HANDLE;
  1427.     goto exit;
  1428.     } else {
  1429.     Fsutil_HandleUnlock(prefixHandle1Ptr);
  1430.     }
  1431.     if (paramsPtr->prefixID2.serverID != rpc_SpriteID) {
  1432.     /*
  1433.      * Second pathname doesn't even start with us.  However, we are
  1434.      * called in case the first pathname redirects away from us.
  1435.      */
  1436.     prefixHandle2Ptr = (Fs_HandleHeader *)NIL;
  1437.     } else {
  1438.     prefixHandle2Ptr =
  1439.         (*fsio_StreamOpTable[paramsPtr->prefixID2.type].clientVerify)
  1440.         (¶msPtr->prefixID2, clientID, (int *)NIL);
  1441.     if (prefixHandle2Ptr == (Fs_HandleHeader *)NIL) {
  1442.         Fsutil_HandleRelease(prefixHandle1Ptr, FALSE);
  1443.         name1Error = FALSE;
  1444.         status = FS_STALE_HANDLE;
  1445.         goto exit;
  1446.     } else {
  1447.         Fsutil_HandleUnlock(prefixHandle2Ptr);
  1448.     }
  1449.     }
  1450.  
  1451.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1452.     if (command == RPC_FS_RENAME) {
  1453.     fs_Stats.srvName.renames++;
  1454.     command = FS_DOMAIN_RENAME;
  1455.     } else if (command == RPC_FS_LINK) {
  1456.     fs_Stats.srvName.hardLinks++;
  1457.     command = FS_DOMAIN_HARD_LINK;
  1458.     } else {
  1459.     printf( "Fsrmt_Rpc2Path: Bad command %d\n", command);
  1460.     status = FS_INVALID_ARG;
  1461.     }
  1462.     if (status == SUCCESS) {
  1463.     status = (*fs_DomainLookup[domainType][command])(prefixHandle1Ptr,
  1464.             pathDataPtr->path1, prefixHandle2Ptr, pathDataPtr->path2,
  1465.             lookupArgsPtr, &newNameInfoPtr, &name1Error);
  1466.     }
  1467.     Fsutil_HandleRelease(prefixHandle1Ptr, FALSE);
  1468.     if (prefixHandle2Ptr != (Fs_HandleHeader *)NIL) {
  1469.     Fsutil_HandleRelease(prefixHandle2Ptr, FALSE);
  1470.     }
  1471. exit:
  1472.     replyParamsPtr = (Fs_2PathReply *) malloc(sizeof (Fs_2PathReply));
  1473.     replyParamsPtr->name1ErrorP = name1Error;
  1474.     storagePtr->replyParamPtr = (Address) replyParamsPtr;
  1475.     storagePtr->replyParamSize = sizeof (Fs_2PathReply);
  1476.     if (status == FS_LOOKUP_REDIRECT) {
  1477.     replyParamsPtr->prefixLength = newNameInfoPtr->prefixLength;
  1478.     storagePtr->replyDataPtr = (Address) newNameInfoPtr;
  1479.     storagePtr->replyDataSize = sizeof(int) +
  1480.                 strlen(newNameInfoPtr->fileName) + 1;
  1481.     } else {
  1482.     replyParamsPtr->prefixLength = 0;
  1483.     /*
  1484.      * Reply data ptr already set to NIL
  1485.      */
  1486.      }
  1487.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1488.     replyMemPtr->paramPtr = (Address) replyParamsPtr;
  1489.     replyMemPtr->dataPtr = (Address) storagePtr->replyDataPtr;
  1490.     Rpc_Reply(srvToken, status, storagePtr, 
  1491.           (int (*)()) Rpc_FreeMem, (ClientData) replyMemPtr);
  1492.  
  1493.     return(SUCCESS);
  1494. }
  1495.  
  1496.  
  1497. /*
  1498.  *----------------------------------------------------------------------
  1499.  *
  1500.  * FsrmtRename --
  1501.  *
  1502.  *    Stub for renaming a file.
  1503.  *
  1504.  * Results:
  1505.  *    A return status.
  1506.  *
  1507.  * Side effects:
  1508.  *    None.
  1509.  *
  1510.  *----------------------------------------------------------------------
  1511.  */
  1512. ReturnStatus
  1513. FsrmtRename(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1514.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1515.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1516.     char *relativeName1;        /* The new name of the file. */
  1517.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1518.     char *relativeName2;        /* The new name of the file. */
  1519.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1520.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1521.                      * its domain during the lookup. */
  1522.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1523.                  * condition if for the first pathname,
  1524.                  * FALSE means error is on second pathname. */
  1525. {
  1526.     return(TwoNameOperation(RPC_FS_RENAME, prefixHandle1, relativeName1, 
  1527.                      prefixHandle2, relativeName2, lookupArgsPtr, 
  1528.                 newNameInfoPtrPtr, name1ErrorPtr));
  1529. }
  1530.  
  1531.  
  1532. /*
  1533.  *----------------------------------------------------------------------
  1534.  *
  1535.  * FsrmtHardLink --
  1536.  *
  1537.  *    Stub for making a hard link between two files.
  1538.  *
  1539.  * Results:
  1540.  *    A return status.
  1541.  *
  1542.  * Side effects:
  1543.  *    None.
  1544.  *
  1545.  *----------------------------------------------------------------------
  1546.  */
  1547. ReturnStatus
  1548. FsrmtHardLink(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1549.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1550.     Fs_HandleHeader *prefixHandle1;    /* Token from the prefix table */
  1551.     char *relativeName1;        /* The new name of the file. */
  1552.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1553.     char *relativeName2;        /* The new name of the file. */
  1554.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1555.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server 
  1556.                      * leaves its domain during the lookup*/
  1557.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error is
  1558.                  * for first path, FALSE if for the second. */
  1559. {
  1560.     return(TwoNameOperation(RPC_FS_LINK, prefixHandle1, relativeName1, 
  1561.                      prefixHandle2, relativeName2, lookupArgsPtr, 
  1562.                 newNameInfoPtrPtr, name1ErrorPtr));
  1563. }
  1564.  
  1565.